#include "T9manager.h"


//This routine initializes all variables you need to control
void initData(Data *d){
	d->listat9=NULL;
	d->listat9ita=NULL;
	d->listat9eng=NULL;
	d->currentnode=NULL;
	d->currentword=NULL;
	d->tempstring=NULL;
	d->tempnum=NULL;
	d->tempchar=NULL;
	d->dictionary=NULL;
	d->dictionaryEng=NULL;
	d->dictionaryIta=NULL;
	d->icon=NULL;
	d->gui=NULL;
	d->charnumber=0;
	d->tempstring=(char*)malloc(wordlen*sizeof(char));
	d->tempstring[0]='\0';
	d->tempnum=(char*)malloc(wordlen*sizeof(char));
	d->tempnum[0]='\0';
	d->tempchar=(char*)malloc(wordlen*sizeof(char));
	d->tempchar[0]='\0';
	d->dictionary=(char*)malloc(pathlen*sizeof(char));
	d->dictionaryIta=(char*)malloc(pathlen*sizeof(char));
	d->dictionaryEng=(char*)malloc(pathlen*sizeof(char));
	d->icon=(char*)malloc(pathlen*sizeof(char));
	d->gui=(char*)malloc(pathlen*sizeof(char));	
	d->begin=BeginTimer();
	d->lastClickedButton=-1;
	d->state=0;   	
	
}

int readConfigFile(char* configpath,Data *d){

	FILE* fp;
	char line[pathlen];
	fp=fopen(configpath,"r");
	if (fp==NULL) {
		printf("error in reading config file");
		return 0;
	}
	int i=0;
	while (fgets(line,sizeof(line),fp ) != NULL ) {
		if(i==1){
			strcpy(d->dictionaryIta,(strstr(line,":"))+sizeof(char));
			char x='\0';
			d->dictionaryIta[strlen(d->dictionaryIta)-1]=x;		
		}
		else if(i==2){
			strcpy(d->dictionaryEng,(strstr(line,":"))+sizeof(char));
			char x='\0';
			d->dictionaryEng[strlen(d->dictionaryEng)-1]=x;	
		}
		else if(i==3){
			strcpy(d->gui,(strstr(line,":"))+sizeof(char));
			char x='\0';
			d->gui[strlen(d->gui)-1]=x;			
		}

		else if(i==4){
			strcpy(d->icon,(strstr(line,":"))+sizeof(char));
			char x='\0';
			d->icon[strlen(d->icon)-1]=x;
		}
		i++;		
	}		
	fclose(fp);
	return 1;		
}



struct elementonumerico* inserisciNuovoNodo(struct elementonumerico **nuovoNodo,struct elementonumerico* elementoprev){
	struct elementonumerico *newnode;
	newnode=(struct elementonumerico*)malloc(sizeof(struct elementonumerico));
	newnode->element2=NULL;
	newnode->element3=NULL;
	newnode->element4=NULL;
	newnode->element5=NULL;
	newnode->element6=NULL;
	newnode->element7=NULL;
	newnode->element8=NULL;
	newnode->element9=NULL;
	newnode->elementoprec=elementoprev;
	newnode->paroleHead=NULL;
	newnode->paroleTail=NULL;	
	nuovoNodo=&newnode; 
	return newnode;
}

void inserisciParola(struct parola **head,struct parola **tail,char *str,double count){


	struct parola *newNode;
	struct parola *temp=*head;
	struct parola *temp2=*head;
	int alreadyKnown=0;
	while(temp2!=NULL){
		if(strcmp(temp2->str,str)==0){
			alreadyKnown=1;
		}
		temp2=temp2->next;
	}
	if(alreadyKnown==0){
		newNode=(struct parola*)malloc(sizeof(struct parola));
		char *newWord=(char *)malloc(wordlen*sizeof(char));
		strcpy(newWord,str);
		newNode->str=newWord;
		newNode->count=count;
		if (*head==NULL){
			newNode->next=NULL;
			newNode->prev=NULL;
			*head=newNode;
			*tail=newNode;
			return;
		
		}
	
		while ((temp!=NULL)&& (temp->count > newNode->count)) {
			temp=temp->next;
		}
		if (temp==*head) {
			(*head)=newNode;
			temp->prev=newNode;
			newNode->next=temp;
			newNode->prev=NULL;
			return;
		}else if (temp==NULL) {
			(*tail)->next=newNode;
			newNode->prev=(*tail);
			newNode->next=NULL;
			(*tail)=newNode;
			return;
		}else {
			newNode->next=temp;
			newNode->prev=temp->prev;
			temp->prev->next=newNode;
			temp->prev=newNode;
			return;
		}

	}
	else
		return;	
}



struct elementonumerico *inserisciElemento(struct elementonumerico **lista, char* cod, char* word,double count){
	struct elementonumerico *listat9=*lista;
	if (listat9==NULL){
		listat9=(struct elementonumerico*)malloc(sizeof(struct elementonumerico));
		listat9->element2=NULL;
		listat9->element3=NULL;
		listat9->element4=NULL;
		listat9->element5=NULL;
		listat9->element6=NULL;
		listat9->element7=NULL;
		listat9->element8=NULL;
		listat9->element9=NULL;
		listat9->elementoprec=listat9;
		listat9->paroleHead=NULL;
		listat9->paroleTail=NULL;
	}
	int i;
	int c=strlen(cod);
	struct elementonumerico* temp=listat9;
	for(i=0;i<c;i++){
		struct elementonumerico *tempElement,*newnewElement;
		switch (cod[i]) {
			case '2':
				tempElement=temp->element2;
				break;
			case '3':
				tempElement=temp->element3;
				break;
			case '4':
				tempElement=temp->element4;
				break;
			case '5':
				tempElement=temp->element5;
				break;
			case '6':
				tempElement=temp->element6;
				break;
			case '7':
				tempElement=temp->element7;
				break;
			case '8':
				tempElement=temp->element8;
				break;
			case '9':
				tempElement=temp->element9;
				break;
			default:
				break;
		}
		
		if(tempElement==NULL){
	
		newnewElement=inserisciNuovoNodo(&newnewElement,temp);
			switch (cod[i]) {
				case '2':
					temp->element2=newnewElement;
					break;
				case '3':
					temp->element3=newnewElement;
					break;
				case '4':
					temp->element4=newnewElement;
					break;
				case '5':
					temp->element5=newnewElement;
					break;
				case '6':
					temp->element6=newnewElement;
					break;
				case '7':
					temp->element7=newnewElement;
					break;
				case '8':
					temp->element8=newnewElement;
					break;
				case '9':
					temp->element9=newnewElement;
					break;
				default:
					break;
			}
			
			
		temp=newnewElement;
		
		}
		else {
		
			switch (cod[i]) {
				case '2':
					temp=temp->element2;
					break;
				case '3':
					temp=temp->element3;
					break;
				case '4':
					temp=temp->element4;
					break;
				case '5':
					temp=temp->element5;
					break;
				case '6':
					temp=temp->element6;
					break;
				case '7':
					temp=temp->element7;
					break;
				case '8':
					temp=temp->element8;
					break;
				case '9':
					temp=temp->element9;
					break;
				default:
					break;
			}
		}
	}
	inserisciParola(&(temp->paroleHead),&(temp->paroleTail),word,count);
	return listat9;
}  


struct elementonumerico* initDictionary(char* path, struct elementonumerico* currentlist){
	FILE* fp;
	fp=fopen(path,"r");
	if (fp==NULL) {
		printf("errore in lettura file");
		return 0;
	}
	char* cod=(char*)malloc(wordlen*sizeof(char));
	char* word=(char*)malloc(wordlen*sizeof(char));
	char* count=(char*)malloc(wordlen*sizeof(char));
	while (1){
		if(fscanf(fp,"%s",cod)!=EOF){
		fscanf(fp,"%s",word);
		fscanf(fp,"%s",count);
		(currentlist)=inserisciElemento(&(currentlist),cod,word,atof(count));
		}
		else
			break;
}
	fclose(fp);
	
	return currentlist;
}

struct elementonumerico *findNodeFromCode(struct elementonumerico *fromNode, char toNode){

	struct elementonumerico *tempElement=fromNode;
	switch (toNode) {
		case '2':
			if((fromNode->element2)!=NULL)
			tempElement=fromNode->element2;
			break;
		case '3':
			if(fromNode->element3!=NULL)
			tempElement=fromNode->element3;
			break;
		case '4':
			if(fromNode->element4!=NULL)
			tempElement=fromNode->element4;
			break;
		case '5':
			if(fromNode->element5!=NULL)
			tempElement=fromNode->element5;
			break;
		case '6':
			if(fromNode->element6!=NULL)
			tempElement=fromNode->element6;
			break;
		case '7':
			if(fromNode->element7!=NULL)
			tempElement=fromNode->element7;
			break;
		case '8':
			if(fromNode->element8!=NULL)
			tempElement=fromNode->element8;
			break;
		case '9':
			if(fromNode->element9!=NULL)
			tempElement=fromNode->element9;
			break;
		default:
			break;
	}
	
	return tempElement;
	

}





char* findWord(char code, Data *d){
	char* str1=NULL;
	int countspecialchar=0;
	int counttempstringspecialchar=0;
	struct elementonumerico* temp=NULL;
	temp=findNodeFromCode(d->currentnode,code);
	if(temp!=d->currentnode)
		d->charnumber++;
	if((temp->paroleHead)!=NULL && (temp!=d->currentnode)){
		int*  accentedchars=(int*)malloc(strlen(temp->paroleHead->str)*sizeof(int));
		int*  accentedchars2=(int*)malloc(strlen(d->tempstring)*sizeof(int));
		accentedchars=FindAccentedChar(temp->paroleHead->str, accentedchars);
		accentedchars2=FindAccentedChar(d->tempstring, accentedchars2);
		int i=0;
		i= accentedchars[0];
		while(i!=-1){
			countspecialchar++;
			i= accentedchars[countspecialchar];
		}
		i= accentedchars2[0];
		
		while(i!=-1){
			counttempstringspecialchar++;
			i= accentedchars2[counttempstringspecialchar];
		}
	}	
	
	if((temp->paroleHead)!=NULL && (temp!=d->currentnode) && (strlen(temp->paroleHead->str)==(strlen(d->tempstring)+1+(countspecialchar-counttempstringspecialchar)))){
				
		d->currentnode=temp;
		d->currentword=d->currentnode->paroleHead;
		strcpy(d->tempstring,d->currentword->str);
		str1=d->currentnode->paroleHead->str;
	}
	else{
		d->currentnode=temp;
		char* nga;
		nga=(char*)malloc(4*sizeof(char));
		switch(code){
				
			case '2':
				nga="a";
				break;
				
			case '3':
				nga="d";
				break;
				
			case '4':
				nga="g";
				break;
				
			case '5':
				nga="j";
				break;
				
			case '6':
				nga="m";
				break;
				
			case '7':
				nga="p";
				break;
				
			case '8':
				nga="t";
				break;
				
			case '9':
				nga="w";
				break;
				
			default:
				break;
		}
	
	d->tempstring=strcat(d->tempstring,nga);
	str1=d->tempstring;
	}

return str1;
	
	
}



char* findNextWord(struct parola *fromNode,struct parola* head,Data *d){
	if(fromNode!=NULL){
		if (strcmp(d->currentword->str,d->tempstring)==0 && (strlen(d->tempstring)>0)) {
			
			if(fromNode->next!=NULL){
			d->currentword=fromNode->next;
			strcpy(d->tempstring,d->currentword->str);
			
				return fromNode->next->str;
			}
			else
				d->currentword=head;
				strcpy(d->tempstring,d->currentword->str);
				return head->str;
		}
	
		else{
			return d->tempstring;
		}
	}
	else{
		return d->tempstring;
	}
	
}
	

char* findPrevWord(Data *d){
	int i=0,countspecialchar=0;
	int*  accentedchars=(int*)malloc(strlen(d->tempstring)*sizeof(int));
	accentedchars=FindAccentedChar(d->tempstring, accentedchars);
	i= accentedchars[0];
	while(i!=-1){
		countspecialchar++;
		i= accentedchars[countspecialchar];
		}

	if(d->currentword==NULL){
		//Enter here ONLY if you have never found a word in the dictionary//
		if((strlen(d->tempstring)-countspecialchar)==d->charnumber){
	//If there is a node, but not the list of words, runs to the previous node and remove a letter//		
			d->currentnode=d->currentnode->elementoprec;
		if( accentedchars[countspecialchar-1]==(strlen(d->tempstring)-2))
			d->tempstring=substring_r(d->tempstring, d->tempstring, 0, strlen(d->tempstring)-3);
		else
			d->tempstring=substring_r(d->tempstring, d->tempstring, 0, strlen(d->tempstring)-2);		
			d->charnumber=d->charnumber-1;
		return d->tempstring;
			
		}
		else {	
			//If there is no previous node deletes a letter//			
			if( accentedchars[countspecialchar-1]==(strlen(d->tempstring)-2))
				d->tempstring=substring_r(d->tempstring, d->tempstring, 0, strlen(d->tempstring)-3);
			else
				d->tempstring=substring_r(d->tempstring, d->tempstring, 0, strlen(d->tempstring)-2);
			return d->tempstring;
		}	
	}
	else{
		//Enter here if if finds a node that contains words while searching//
		int countspecialcharprev=0;
		if(strcmp(d->currentword->str,d->tempstring)!=0){
			if((d->currentnode->elementoprec->paroleHead)!=NULL){
				int j=0;
				int*  accentedcharsprev=(int*)malloc(strlen(d->currentnode->elementoprec->paroleHead->str)*sizeof(int));
				 accentedcharsprev=FindAccentedChar(d->currentnode->elementoprec->paroleHead->str, accentedcharsprev);
				j= accentedcharsprev[0];
					while(j!=-1){
					countspecialcharprev++;
					j= accentedcharsprev[countspecialcharprev];
					}
			}	
			//The displayed word is not in the dictionary//
		if((d->currentnode->elementoprec->paroleHead)!=NULL && strlen(d->currentnode->elementoprec->paroleHead->str)==(strlen(d->tempstring)-1-(countspecialchar-countspecialcharprev))){
			//If the previous node exists and contains a word, it appears//
			d->charnumber=d->charnumber-1;				
			d->currentnode=d->currentnode->elementoprec;			
			d->currentword=d->currentnode->paroleHead;
			strcpy(d->tempstring,d->currentword->str);
			return d->currentword->str;
		}
			
		if((strlen(d->tempstring)-countspecialchar)==d->charnumber){
			//If there is a node, but not the word,it returns to the previous node....//
			d->currentnode=d->currentnode->elementoprec;
			d->charnumber=d->charnumber-1;
		}
		//...and deletes a character
		if( accentedchars[countspecialchar-1]==(strlen(d->tempstring)-2))
			d->tempstring=substring_r(d->tempstring, d->tempstring, 0, strlen(d->tempstring)-3);
		else
			d->tempstring=substring_r(d->tempstring, d->tempstring, 0, strlen(d->tempstring)-2);
		if(strlen(d->tempstring)==0){
			d->currentnode=d->listat9;
			d->charnumber=0;
			d->tempstring[0]='\0';
			d->currentword=NULL;
		}
	return d->tempstring;
		
	}
else {
	//Enter here if the displayed word is contained in the dictionary
	if (strlen(d->currentword->str)-countspecialchar>1) {
		//if it contains more than one character runs to the previous node and if.....//
		d->currentnode=d->currentnode->elementoprec;
		d->charnumber=d->charnumber-1;
		if(d->currentnode->paroleHead!=NULL){
			//.....contains a word, it appears//
			d->currentword=d->currentnode->paroleHead;
			strcpy(d->tempstring,d->currentword->str);
			return d->currentword->str;
		}
		else {
			//it does not contain a word so a character is deleted//
			if( accentedchars[countspecialchar-1]==(strlen(d->tempstring)-2))
				d->tempstring=substring_r(d->tempstring, d->tempstring, 0, strlen(d->tempstring)-3);
			else
				d->tempstring=substring_r(d->tempstring, d->tempstring, 0, strlen(d->tempstring)-2);
				return d->tempstring;
		}
	}
	else{
//if it has only one character,the text is cleared and CurrentNode is set equal to the root of the list//
		d->currentnode=d->listat9;
		d->charnumber=0;
		d->tempstring[0]='\0';
		d->currentword=NULL;
		return "errore";
	}
}

}
}



char* getCodeFromString(char *currentString){

	char *newCode=(char*)malloc((strlen(currentString)+1)*sizeof(char));
	char *buffer=(char *)malloc(2*sizeof(char));
	int i=0;int j=0;
	for (i=0,j=0; i<strlen(currentString); i++,j++) {
		switch (currentString[i]) {
			case 'a':
			case 'b':
			case 'c':
			case 'A':
			case 'B':
			case 'C':
				newCode[j]='2';
				break;
			case 'd':
			case 'e':
			case 'f':
			case 'D':
			case 'E':
			case 'F':
				newCode[j]='3';
				break;
			case 'g':
			case 'h':
			case 'i':
			case 'G':
			case 'H':
			case 'I':
				newCode[j]='4';
				break;
			case 'j':
			case 'k':
			case 'l':
			case 'J':
			case 'K':
			case 'L':
				newCode[j]='5';
				break;
			case 'm':
			case 'n':
			case 'o':
			case 'M':
			case 'N':
			case 'O':
				newCode[j]='6';
				break;
			case 'p':
			case 'q':
			case 'r':
			case 's':
			case 'P':
			case 'Q':
			case 'R':
			case 'S':
				newCode[j]='7';
				break;
			case 't':
			case 'u':
			case 'v':
				newCode[j]='8';
				break;
			case 'w':
			case 'x':
			case 'y':
			case 'z':
			case 'W':
			case 'X':
			case 'Y':
			case 'Z':
				newCode[j]='9';
				break;

			default:					
				buffer=substring_r(buffer,currentString,i,i+1);
				if ((strcmp(buffer,"è")==0)) {
				newCode[j]='3';
				i=i+1;
				}
				else if((strcmp(buffer,"à")==0)){
					newCode[j]='2';
					i=i+1;
				}
				else if((strcmp(buffer,"ì")==0)){
					newCode[j]='4';
					i=i+1;
				}
				else if((strcmp(buffer,"ò")==0)){
					newCode[j]='6';
					i=i+1;
				}
				else if((strcmp(buffer,"ù")==0)){
					newCode[j]='8';
					i=i+1;
				}
			break;
		}
	}
	newCode[j]='\0';
	return newCode;
}



void visitWordList(struct elementonumerico *node,FILE *fp){
	if(strlen(node->paroleHead->str)>=1){
		fprintf(fp,"%s %s %2.f\n", getCodeFromString(node->paroleHead->str),node->paroleHead->str,node->paroleHead->count);
		struct parola *tempWord=node->paroleHead;
		while (tempWord->next != NULL) {
			if(strlen(tempWord->str)>=1){
				tempWord=tempWord->next;
				fprintf(fp,"%s %s %2.f\n", getCodeFromString(tempWord->str),tempWord->str,tempWord->count);
			}
		}
	}
}

void visit(struct elementonumerico *node,FILE *fp){

	if (node->paroleHead!=NULL) {
	visitWordList(node,fp);
	}else {

	}

}

void preorder(struct elementonumerico *node,FILE *fp,void (*visit)(struct elementonumerico *,FILE *fp)){
	
	if (node==NULL) {
		return;
	}	
	(*visit)(node,fp);
	preorder(node->element2,fp,visit);
	preorder(node->element3,fp,visit);
	preorder(node->element4,fp,visit);
	preorder(node->element5,fp,visit);
	preorder(node->element6,fp,visit);
	preorder(node->element7,fp,visit);
	preorder(node->element8,fp,visit);
	preorder(node->element9,fp,visit);
}


void saveDictionary(struct elementonumerico *listat9,char* path){
	FILE* fp;
	fp=fopen(path,"w");
	if (fp==NULL) {
		printf("error in reading file");
		return ;
	}
	fprintf(fp, "\n");
	preorder(listat9,fp,visit);
	fclose(fp);
	
}


